package com.mine.androidlearn.api;

import android.content.Context;

import com.mine.androidlearn.api.Interceptor.HttpSignatureInterceptor;
import com.mine.androidlearn.api.Interceptor.LiveNetworkMonitor;
import com.mine.androidlearn.api.Interceptor.NetworkStateInterceptor;
import com.mine.androidlearn.api.bean.WeatherInfoBean;

import org.apache.http.conn.ssl.AllowAllHostnameVerifier;

import java.security.cert.CertificateException;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import rx.Observable;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Func1;
import rx.schedulers.Schedulers;

/**
 * 
 * @author: hujianghao5
 * @version: V1.0 2018/8/3 20:43
 */
public class RetrofitUtil implements IGlobalManager {

    /**
     * 服务器地址
     */
//    private static final String API_HOST = BuildConfig.SERVER_URL;
    private static final String API_HOST ="http://api.avatardata.cn/";
    private static Retrofit retrofit;
    /**
     * 转变Observable类型并且封装了线程切换的操作
     */
    @SuppressWarnings("unchecked")
    final Observable.Transformer transformer = new Observable.Transformer() {
        @Override
        public Object call(Object observable) {
            return ((Observable) observable).subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .flatMap(new Func1() {
                        @Override
                        public Object call(Object response) {
                            return flatResponse((HttpResponse<Object>) response);
                        }
                    });
        }
    };


    /**
     * 测试学习用，未做实际flatResponse处理
     */
    @SuppressWarnings("unchecked")
    final Observable.Transformer transformer2 = new Observable.Transformer() {
        @Override
        public Object call(Object observable) {
            return ((Observable) observable).subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .flatMap(new Func1() {
                        @Override
                        public Object call(Object response) {
                            return flatResponse2(response);
                        }
                    });
        }
    };
    /**
     * 转变Observable类型并且封装了线程切换的操作
     */
    @SuppressWarnings("unchecked")
    final Observable.Transformer refreshTokenTransformer = new Observable.Transformer() {
        @Override
        public Object call(Object observable) {
            return ((Observable) observable).subscribeOn(Schedulers.io())
                    .flatMap(new Func1() {
                        @Override
                        public Object call(Object response) {
                            return flatResponse((HttpResponse<Object>) response);
                        }
                    });
        }
    };
    private final Context mContext;

    public RetrofitUtil(Context context) {
        mContext = context;
    }

    /**
     * 获取HttpClient（不验证https证书）
     *
     * @param context
     * @return
     */
    public static OkHttpClient getUnsafeOkHttpClient(Context context) {

        try {
            // Create a trust manager that does not validate certificate chains
            final TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
                @Override
                public void checkClientTrusted(
                        java.security.cert.X509Certificate[] chain,
                        String authType) throws CertificateException {
                }

                @Override
                public void checkServerTrusted(
                        java.security.cert.X509Certificate[] chain,
                        String authType) throws CertificateException {
                }

                @Override
                public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                    return new java.security.cert.X509Certificate[0];
                }
            }};

            // Install the all-trusting trust manager
            final SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, trustAllCerts,
                    new java.security.SecureRandom());
            // Create an ssl socket factory with our all-trusting manager
            final SSLSocketFactory sslSocketFactory = sslContext
                    .getSocketFactory();


            OkHttpClient.Builder clientBuilder = new OkHttpClient().newBuilder();
            HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
            httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
            HttpSignatureInterceptor httpSignatureInterceptor = new HttpSignatureInterceptor();
            NetworkStateInterceptor networkStateInterceptor
                    = new NetworkStateInterceptor(new LiveNetworkMonitor(context));
            OkHttpClient okHttpClient = clientBuilder
                    .connectTimeout(10, TimeUnit.SECONDS)
                    .writeTimeout(10, TimeUnit.SECONDS)
                    .readTimeout(10, TimeUnit.SECONDS)
                    .sslSocketFactory(sslSocketFactory)
                    .hostnameVerifier(new AllowAllHostnameVerifier())
                    .addInterceptor(networkStateInterceptor)
                    .addInterceptor(httpLoggingInterceptor)
                    .addInterceptor(httpSignatureInterceptor).build();

            return okHttpClient;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }

    /**
     * 获取Retrofit
     *
     * @return
     */
    private static Retrofit getRetrofit(Context context) {
        if (retrofit == null) {
//            OkHttpClient.Builder clientBuilder = new OkHttpClient().newBuilder();
//
//            HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
//            httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
//            clientBuilder.addInterceptor(httpLoggingInterceptor);
            String host = API_HOST;// TODO: 2018/8/3 question 可以配置测试用地址
//            String debugHost = GlobalVariables.getInstance(context).getDebugMspUrl();
//            if (!TextUtils.isEmpty(debugHost)) {
//                host = debugHost;
//            }
            retrofit = new Retrofit.Builder().client(getUnsafeOkHttpClient(context))
                    .baseUrl(host)
                    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
        }
        return retrofit;
    }

    /**
     * 获取接口Service
     *
     * @param <T>
     * @param tClass
     * @return
     */
    public <T> T getService(Class<T> tClass) {
        return getRetrofit(mContext).create(tClass);
    }

//    /**
//     * 获取接口Proxy
//     *
//     * @param tClass
//     * @param <T>
//     * @return
//     */
//    @SuppressWarnings("unchecked")
//    public <T> T getProxy(Class<T> tClass) {
//        T t = getRetrofit(mContext).create(tClass);
//        return (T) Proxy.newProxyInstance(tClass.getClassLoader(), new Class<?>[]{tClass}
//                , new ProxyHandler(mContext, t, this));
//    }


    /**
     * 对网络接口返回的Response进行分割操作
     *
     * @param response
     * @param <T>
     * @return
     */
    public <T> Observable<T> flatResponse(final HttpResponse<T> response) {
        return Observable.create(new Observable.OnSubscribe<T>() {
            @Override
            public void call(Subscriber<? super T> subscriber) {
                if (response.isSuccess()) {
                    if (!subscriber.isUnsubscribed()) {
                        subscriber.onNext(response.getData());
                    }
                } else {
                    if (!subscriber.isUnsubscribed()) {
//                        subscriber.onError(new ApiException(response.getCode(), response.getMsg()));
                    }
                }

                if (!subscriber.isUnsubscribed()) {
                    subscriber.onCompleted();
                }

            }
        });
    }


    /**
     * 测试学习用，未做实际flatResponse
     * @param response
     * @param <T>
     * @return
     */
    public <T> Observable<T> flatResponse2(final T response) {
        return Observable.create(new Observable.OnSubscribe<T>() {
            @Override
            public void call(Subscriber<? super T> subscriber) {
                if (!subscriber.isUnsubscribed()) {
                    subscriber.onNext(response);
                }
            }
        });
    }

    /**
     * 调度器
     *
     * @param <T>
     * @return
     */
    protected <T> Observable.Transformer<HttpResponse<T>, T> applySchedulers() {
        return (Observable.Transformer<HttpResponse<T>, T>) transformer;
    }


    /**
     * 测试学习用，未做实际flatResponse
     * @param <T>
     * @return
     */
    protected <T> Observable.Transformer<WeatherInfoBean, T> applySchedulers2() {
        return (Observable.Transformer<WeatherInfoBean, T>) transformer2;
    }

    /**
     * 调度器
     *
     * @param <T>
     * @return
     */
    protected <T> Observable.Transformer<HttpResponse<T>, T> applySchedulersForRefreshToken() {
        return (Observable.Transformer<HttpResponse<T>, T>) refreshTokenTransformer;
    }

    @Override
    public void exitLogin() {
    }
}
